package in.co.codedoc.tomcat;

import in.co.codedoc.framework.ServiceInvoker;
import in.co.codedoc.framework.UploadedFiles;
import in.co.codedoc.ioc.IOCContainer;
import in.co.codedoc.sql.SessionLocal;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.oreilly.servlet.MultipartWrapper;

@SuppressWarnings("serial")
public abstract class InvokeableServletBase
	extends HttpServlet
{
	protected abstract org.apache.log4j.Logger GetLogger();
	
	public abstract void serviceImpl(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException;
	
	@SuppressWarnings("unchecked")
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException
	{
		String contentType = request.getContentType();
		
		MultipartWrapper multipartRequest = null;
		
		try
		{
			if(contentType != null && (contentType.toLowerCase().startsWith("multipart/form-data")))
			{
				ServiceInvoker si = IOCContainer.Lookup(ServiceInvoker.class);
				
				if((si.GetUploadTempDirectory() == null) || (si.GetUploadTempDirectory().equals("")))
				{
					throw new RuntimeException
					(
						"ServiceInvoker.uploadTempDirectory should be configured for handling file uploads." + 
						" Contact the system administrator."
					);
				}
				
				 
				multipartRequest = new MultipartWrapper(request, si.GetUploadTempDirectory(),si.GetUploadSizeLimit());
				
				request = multipartRequest;
				
				Enumeration files = multipartRequest.getFileNames();
				
				while(files.hasMoreElements())
				{
					String name = files.nextElement().toString();
					if(Logger.logger.isDebugEnabled())
					{
						Logger.logger.debug("Uploaded file being added to list:" + name);
					}
					UploadedFiles.AddFile(name,multipartRequest.getFile(name));
				}
			}
			
			try
			{
				SessionLocal.ClearAll();
				
				ServiceInvoker si = IOCContainer.Lookup(ServiceInvoker.class);
				
				si.InvokeService
				(
					this, 
					serviceMethod, 
					new Object[]{request,response}, 
					request,response, 
					GetLogger()
				);
				
			}
			finally
			{
				SessionLocal.ClearAll();
			}
		}
		catch(Throwable th)
		{
			if(multipartRequest != null)
			{
				Logger.logger.error("Excetion while processing multipart request:" + th.getMessage(),th);
			}
			else
			{
				Logger.logger.error("Excetion while request:" + th.getMessage(),th);
			}	
		}
		finally
		{
			UploadedFiles.ClearUploadedFiles();
		}

	}
	
	private static final Method serviceMethod = GetServiceMethod();

	@SuppressWarnings("unchecked")
	private static Method GetServiceMethod()
	{
		Class[] paramTypes = new Class[]{HttpServletRequest.class,HttpServletResponse.class};
		
		try
		{
			return InvokeableServletBase.class.getDeclaredMethod("serviceImpl", paramTypes);
		}
		catch (Throwable th)
		{
			throw new RuntimeException(th);
		} 
	}
}
